package com.example.gateway.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/ip")
public class IpController {

    private static final String BLACKLIST_KEY = "ip:blacklist";
    private static final String WHITELIST_KEY = "ip:whitelist";
    private static final String RATE_LIMIT_PREFIX = "rate_limit:ip:";

    @Autowired
    private ReactiveStringRedisTemplate redisTemplate;

    // 查询黑名单
    @GetMapping("/blacklist")
    public Mono<List<String>> getBlacklist() {
        return redisTemplate.opsForSet().members(BLACKLIST_KEY).collectList();
    }

    // 查询白名单
    @GetMapping("/whitelist")
    public Mono<List<String>> getWhitelist() {
        return redisTemplate.opsForSet().members(WHITELIST_KEY).collectList();
    }

    // 查询所有访问过的IP
    @GetMapping("/accessedIps")
    public Mono<List<String>> getAccessedIps() {
        return redisTemplate.keys("ip:access:*")
                .collectList()
                .map(list -> list.stream()
                        .filter(key -> !key.endsWith(":paths"))
                        .map(key -> key.substring("ip:access:".length()))
                        .collect(Collectors.toList()));
    }

    // 查询指定IP的访问数据
    @GetMapping("/accessInfo/{ip}")
    public Mono<Map<Object, Object>> getAccessInfo(@PathVariable String ip) {
        String key = "ip:access:" + ip;
        return redisTemplate.opsForHash().entries(key)
                .collectMap(Map.Entry::getKey, Map.Entry::getValue);
    }

    // 查询指定IP的访问路径计数
    @GetMapping("/accessPaths/{ip}")
    public Mono<Map<Object, Object>> getAccessPaths(@PathVariable String ip) {
        String key = "ip:access:" + ip + ":paths";
        return redisTemplate.opsForHash().entries(key)
                .collectMap(Map.Entry::getKey, Map.Entry::getValue);
    }

    // 添加黑名单IP
    @PostMapping("/blacklist")
    public Mono<ResponseEntity<String>> addBlacklist(@RequestBody Mono<StringWrapper> body) {
        return body.flatMap(wrapper -> {
            String ip = wrapper.getIp();
            if (ip == null || ip.isEmpty()) {
                return Mono.just(ResponseEntity.badRequest().body("IP不能为空"));
            }
            return redisTemplate.opsForSet().add(BLACKLIST_KEY, ip)
                    .map(count -> ResponseEntity.ok("添加成功"));
        });
    }

    // 添加白名单IP
    @PostMapping("/whitelist")
    public Mono<ResponseEntity<String>> addWhitelist(@RequestBody Mono<StringWrapper> body) {
        return body.flatMap(wrapper -> {
            String ip = wrapper.getIp();
            if (ip == null || ip.isEmpty()) {
                return Mono.just(ResponseEntity.badRequest().body("IP不能为空"));
            }
            return redisTemplate.opsForSet().add(WHITELIST_KEY, ip)
                    .map(count -> ResponseEntity.ok("添加成功"));
        });
    }

    // 删除黑名单IP
    @DeleteMapping("/blacklist/{ip}")
    public Mono<ResponseEntity<String>> removeBlacklist(@PathVariable String ip) {
        return redisTemplate.opsForSet().remove(BLACKLIST_KEY, ip)
                .map(count -> ResponseEntity.ok("删除成功"));
    }

    // 删除白名单IP
    @DeleteMapping("/whitelist/{ip}")
    public Mono<ResponseEntity<String>> removeWhitelist(@PathVariable String ip) {
        return redisTemplate.opsForSet().remove(WHITELIST_KEY, ip)
                .map(count -> ResponseEntity.ok("删除成功"));
    }

    // ------------- 新增：限流参数管理接口 ---------------

    // 查询指定IP限流参数
    @GetMapping("/ratelimit/{ip}")
    public Mono<Map<Object, Object>> getRateLimitParams(@PathVariable String ip) {
        return redisTemplate.opsForHash().entries(RATE_LIMIT_PREFIX + ip)
                .collectMap(Map.Entry::getKey, Map.Entry::getValue);
    }

    // 设置指定IP限流参数，JSON body示例： {"replenishRate":"20","burstCapacity":"30"}
    @PostMapping("/ratelimit/{ip}")
    public Mono<ResponseEntity<String>> setRateLimitParams(@PathVariable String ip,
                                                           @RequestBody Mono<Map<String, String>> body) {
        return body.flatMap(params -> {
            if (params.isEmpty()) {
                return Mono.just(ResponseEntity.badRequest().body("限流参数不能为空"));
            }
            return redisTemplate.opsForHash().putAll(RATE_LIMIT_PREFIX + ip, params)
                    .map(ok -> ResponseEntity.ok("限流参数设置成功"));
        });
    }

    // 删除指定IP限流参数
    @DeleteMapping("/ratelimit/{ip}")
    public Mono<ResponseEntity<String>> deleteRateLimitParams(@PathVariable String ip) {
        return redisTemplate.delete(RATE_LIMIT_PREFIX + ip)
                .map(count -> ResponseEntity.ok("限流参数删除成功"));
    }

    // 请求体包装类
    public static class StringWrapper {
        private String ip;
        public String getIp() { return ip; }
        public void setIp(String ip) { this.ip = ip; }
    }

// ------------- 保留：统一参数管理接口（仅拉黑阈值） -------------

    private static final String AUTO_BLOCK_THRESHOLD_KEY = "config:autoBlockThreshold";

    // 获取当前拉黑阈值配置
    @GetMapping("/config")
    public Mono<Map<String, Object>> getBlockConfig() {
        Mono<String> autoBlock = redisTemplate.opsForValue().get(AUTO_BLOCK_THRESHOLD_KEY);

        return autoBlock.defaultIfEmpty("200")
                .map(value -> {
                    Map<String, Object> res = Map.of(
                            "autoBlockThreshold", Integer.parseInt(value)
                    );
                    return res;
                });
    }

    // 修改拉黑阈值配置（请求体为 JSON）
    @PostMapping("/config")
    public Mono<ResponseEntity<String>> updateBlockConfig(@RequestBody Map<String, Object> body) {
        Object blockVal = body.get("autoBlockThreshold");

        if (blockVal == null) {
            return Mono.just(ResponseEntity.badRequest().body("autoBlockThreshold 不能为空"));
        }

        Mono<Boolean> setBlock = redisTemplate.opsForValue().set(AUTO_BLOCK_THRESHOLD_KEY, blockVal.toString());

        return setBlock.map(result -> ResponseEntity.ok("拉黑参数更新成功"));
    }
}
